import { Module, Provider, DynamicModule } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { getModelForClass, mongoose } from '@typegoose/typegoose';

// const DB = 'mongodb://127.0.0.1:27017';

/**
 * 提供者类型
 */
type ClassType = { new (...args: any[]): any };

/**
 * 数据库模块
 */
@Module({})
export class DbModule {
  /**
   * 静态方法，用于初始化数据库连接
   * @param uri 数据库连接地址
   * @param options 数据库连接选项
   * @returns 动态模块
   */
  static forRoot(envKey: string, options = {}): DynamicModule {
    // 定义提供者数组
    const providers: Provider[] = [
      {
        // 提供数据库连接
        provide: 'DB_CONNECTION',
        inject: [ConfigService],
        // 使用工厂函数连接数据库
        useFactory: (cfg: ConfigService) => {
          const uri = cfg.get<string>(envKey, 'DB_URI');
          return mongoose.connect(uri, options);
        },
      },
    ];
    // 返回动态模块
    return {
      module: DbModule,
      providers,
      exports: providers,
      global: true,
    };
  }

  /**
   * 静态方法，用于初始化数据库模型，主要是功能性模型
   * @param modules 模型数组
   * @returns 动态功能性模块
   */
  static forFeature(modules: ClassType[]): DynamicModule {
    // 遍历modules数组，将每个model的name和getModelForClass函数作为provide和useFactory返回，并转换为Provider类型
    const providers = modules.map((model) => {
      return {
        provide: model.name,
        useFactory: () => getModelForClass(model),
      } as Provider;
    });
    // 返回一个对象，包含module、providers、exports和global属性
    return {
      module: DbModule,
      providers,
      exports: providers,
      global: true,
    };
  }
}
